import 'package:flutter/foundation.dart';
import 'package:flutter_2b_client/utils/Page.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';

typedef QueryPageDataFunction<I> = Future<Page<I>> Function(Pageable pageable);
typedef QuerySliceDataFunction<I> = Future<Slice<I>> Function(
    Pageable pageable);
typedef KeyPathFunction<K, I> = K Function(I item);

_appendPage<K, I>(
    bool last,
    List<I> content,
    PagingController<Pageable, I> pagingController,
    KeyPathFunction<K, I>? keyPathFunction) {
  if (keyPathFunction == null) {
    if (last) {
      pagingController.appendLastPage(content);
    } else {
      pagingController.appendPage(
          content,
          pagingController.nextPageKey?.copy(PageableMergeOption(
              page: pagingController.nextPageKey!.page + 1)));
    }
  } else {
    final newItems = (pagingController.itemList?.toList() ?? []);
    for (var value in content) {
      if (newItems.every(
          (element) => keyPathFunction(element) != keyPathFunction(value))) {
        newItems.add(value);
      }
    }
    pagingController.value = PagingState(
      itemList: newItems,
      error: null,
      nextPageKey: last
          ? null
          : pagingController.nextPageKey?.copy(PageableMergeOption(
              page: pagingController.nextPageKey!.page + 1)),
    );
  }
}

usePagingControllerListener<I, K>(
    PagingController<Pageable, I> pagingController,
    QueryPageDataFunction<I> query,
    KeyPathFunction<K, I>? keyPathFunction,
    [List<Object?>? keys]) {
  useEffect(() {
    listener(Pageable pageKey) {
      query(pageKey).then((value) {
        _appendPage(
            value.last, value.content, pagingController, keyPathFunction);
      });
    }

    pagingController.refresh();

    pagingController.addPageRequestListener(listener);
    return () {
      pagingController.removePageRequestListener(listener);
    };
  }, keys);
}

useSlicingControllerListener<I, K>(
    PagingController<Pageable, I> pagingController,
    QuerySliceDataFunction<I> query,
    KeyPathFunction<K, I>? keyPathFunction,
    [List<Object?>? keys]) {
  useEffect(() {
    listener(Pageable pageKey) {
      query(pageKey).then((value) {
        _appendPage(
            value.last, value.content, pagingController, keyPathFunction);
      });
    }

    pagingController.refresh();

    pagingController.addPageRequestListener(listener);
    return () {
      pagingController.removePageRequestListener(listener);
    };
  }, keys);
}

deletePageItemAndSupplementOne<Item>(PagingController<Pageable,Item> pagingController,
    bool Function(Item element) filter ,
    Future<Page<Item>> Function(Pageable pageable) queryOne,
    ValueNotifier<int> totalElementsState) async {
  var newItemList = pagingController.itemList
      ?.where(filter)
      .toList();

  if (pagingController.nextPageKey != null &&
      pagingController.itemList != null) {
    var queryPage =
        await queryOne(Pageable(
            page:
            pagingController.itemList!.length,
            size: 1));

    newItemList?.addAll(queryPage.content);
  }
  pagingController.itemList = newItemList;
  totalElementsState.value-=1;
}
